input_NumString_to_8421BCD2HEX PROTO :WORD,:WORD
BCD2HEX PROTO :WORD
_printf PROTO :WORD
_scanf PROTO :WORD
_clear_KBbuf PROTO :WORD
.CODE
input_NumString_to_8421BCD2HEX PROC near USES si di bx cx dx,NumString,Var;int input_NumString_to_8421BCD2HEX(int pNumString*,int pVar*);
    local negative_flag:WORD;BOOL negative_flag;
	local local_buf[4]:BYTE
	mov si,NumString
	.if BYTE ptr ds:(KEYBOARD ptr [si]).inputCount == NULL;if (KBbuf.inputCount == 1){
		input_NULL:
		mov ax,ERROR_INPUT_STRING_NULL;return ERROR_INPUT_STRING_NULL;}
		ret
	.else;else{
		xor cx,cx;int c = 0; 
		mov cl,ds:(KEYBOARD ptr [si]).inputCount;c = KBbuf.inputCount;
		mov bx,0;int b = 0;
		.if [ds:(KEYBOARD ptr [si]).buffer+bx] == '-';if (KBbuf.buffer[b] == "-"){
			ngin:
			inc bx;b++;
			dec cx;c--;
			mov negative_flag,TRUE;negative_flag = TRUE;}
		.else;else{
			mov negative_flag,FALSE;negative_flag = FALSE;}
			.if [ds:(KEYBOARD ptr [si]).buffer+bx] == '+';if (KBbuf.buffer[b] == "+"){
				inc bx;b++;
				dec cx;c--;
			.endif;}
		.endif;}
	.endif;}
	
	.while [ds:(KEYBOARD ptr [si]).buffer+bx] == '0'
		.if cx == 1
			.break
		.endif
		inc bx
		dec cx
	.endw
	
	.if cx > MaxBit
		mov ax,ERROR_INPUT_NUMBER_OUT_RANGE
		ret
	.endif
	
	lea di,ss:local_buf
	push es
	push ss
	pop es
	push di
	push cx
	mov cx,4
	mov al,0
	cld
	rep stosb
	pop cx
	pop di
	
	
	push di
	mov ax,4
	sub ax,cx
	add di,ax
	ASCII2BCD:
	.if [ds:(KEYBOARD ptr [si]).buffer+bx] < '0'
		jmp not_a_mumber
	.elseif [ds:(KEYBOARD ptr [si]).buffer+bx] > '9'
		not_a_mumber:
		mov ax,ERROR_INPUT_NOT_A_NUMBER
		pop di
		pop es
		ret
	.endif
	xor ax,ax
	mov al,[ds:(KEYBOARD ptr [si]).buffer+bx]
	sub al,'0'
	cld
	stosb
	inc bx
	loop ASCII2BCD
	pop di
	pop es
	mov ax,WORD ptr ss:[di+2]
	shl al,4
	or al,ah
	mov dx,WORD ptr ss:[di]
	shl dl,4
	or dl,dh
	mov ah,dl
	invoke BCD2HEX,ax
	.if negative_flag == TRUE
		.if ax != 0
		neg ax
		.else
			mov ax,ERROR_NEGATIVE_ZERO
			ret
		.endif
	.endif
	mov di,Var
	mov ds:[di],ax
	xor ax,ax
	ret
input_NumString_to_8421BCD2HEX ENDP

BCD2HEX PROC USES cx dx bx,indec
	xor ax,ax
	xor dx,dx
	mov ax,indec
	mov cx,1
	mov dx,ax
	and dx,0fh
	l2:
	push cx
	shr ax,4
	push ax
	mov ax,0ah
	jmp next1
	l1:
	mov bl,0ah
	mul bl
	next1:
	loop l1
	pop bx
	push bx
	and bx,0fh
	push dx
	mul bx
	pop dx
	add dx,ax
	pop ax
	pop cx
	inc cx
	cmp cx,4
	jne l2
	mov ax,dx
	ret
BCD2HEX ENDP

_printf proc near uses bx cx dx,pString
	mov ah,09h
	mov dx,pString
	int 21h
	xor ax,ax
	ret
_printf endp

_scanf proc near uses bx cx dx,pKBbuf
	mov ah,0ah
	mov dx,pKBbuf
	invoke _clear_KBbuf,dx
	int 21h;scanf(pNumString*);
	xor ax,ax
	ret
_scanf endp

_clear_KBbuf proc near,pKBbuf
	pusha
	xor cx,cx
	mov di,pKBbuf
	mov cl,(KEYBOARD ptr [di]).maxInput
	add di,2
	mov al,0
	cld
	rep stosb
	popa
	ret
_clear_KBbuf endp

calculator_Y proc near uses si bx cx dx,pArray
	local i:DWORD
	mov si,pArray
	mov ax,(C_ARRAY ptr [si]).variable_a
	mov bx,(C_ARRAY ptr [si]).variable_b
	imul bx
	mov WORD ptr i,ax
	mov WORD ptr i+2,dx
	mov ax,(C_ARRAY ptr [si]).variable_c
	cwd
	mov bx,(C_ARRAY ptr [si]).variable_d
	idiv bx
	cwd
	add WORD ptr i,ax
	adc WORD ptr i+2,dx
	mov ax,(C_ARRAY ptr [si]).variable_e
	cwd
	sub WORD ptr i,ax
	sbb WORD ptr i+2,dx
	mov ax,WORD ptr i
	mov dx,WORD ptr i+2
	mov WORD ptr (C_ARRAY ptr [si]).Result,ax
	mov WORD ptr (C_ARRAY ptr [si]).Result+2,dx
	xor ax,ax
	ret
calculator_Y endp

;=============================================================
;子程序:转换16位HEX码[8bit]为扩展的BCD码[24bit]
;子程序调用名:HEX2BCD16
;入口参数:ds:[si]=需要转换HEX变量存储地址,16bit
;出口参数:ds:[di]=转换后的BCD变量存储地址,24bit
HEX2BCD16 proc near
;-------------------------------------------------------------
      pusha
      mov ax,[si]
      xor dx,dx
      mov bx,0ah
      div bx
      mov bp,dx
      xor dx,dx
      div bx
      mov cl,04h
      shl dx,cl
      and dx,00f0h
      add bp,dx
      xor dx,dx
      div bx
      mov cl,08h
      shl dx,cl
      and dx,0f00h
      add bp,dx
      xor dx,dx
      div bx
      mov cl,0ch
      shl dx,cl
      and dx,0f000h
      add bp,dx
      xor dx,dx
      div bx
      mov ax,bp
      mov [di],byte ptr dl
      inc di
      mov [di],byte ptr ah
      inc di
      mov [di],byte ptr al
      popa
      ret
HEX2BCD16 endp
;=============================================================

HEX2BCD32 proc near;转换的数值必须小于正整数 655359 否则会发生除法错溢出
	pusha
	mov al,0
	mov cx,5
	cld
	rep stosb
	dec di
	mov ax,[si]
	mov dx,[si+2]
	mov cx,0ah
	.while ax !=0
		mov cx,0ah
		call divdw
		push cx
		mov cx,0ah
		call divdw
		shl cl,4
		pop bx
		or cl,bl
		mov [di],cl
		dec di
	.endw
	popa
	ret
HEX2BCD32 endp

;=============================================================
;子程序:转换内存中8位HEX码为扩展的ASCII码
;子程序调用名:HEX2ASCII
;入口参数:ds:[si]=需要转换HEX变量存储地址,8bit
;         ds:[di]=转换后的ASCII变量存储地址,16bit
;出口参数:ds:[di]=转换后的ASCII变量存储地址,16bit
HEX2ASCII proc near
;-------------------------------------------------------------
      pusha
      MOV DL,byte ptr[si]
      MOV CL,4
      SHR DL,CL;右移4位获得高4位
      ADD DL,030H;0～9加30H,A~F加37H
      CMP DL,'9';将双分支转化为单分支
      JBE NEXT1
      ADD DL,7
NEXT1:MOV byte ptr[di],DL
      INC DI
      MOV DL,byte ptr[si]
      AND DL,0FH;高4位清0获得低4位
      ADD DL,30H
      CMP DL,'9'
      JBE NEXT2
      ADD DL,7
NEXT2:MOV byte ptr[di],DL
      popa
      ret
HEX2ASCII endp
;=============================================================

;=============================================================
;子程序:转换寄存器中的8位HEX码为扩展的ASCII码
;子程序调用名:RHEX2ASCII
;入口参数:dl
;出口参数:ds:[di]=转换后的ASCII变量存储地址,16bit
RHEX2ASCII proc near
;-------------------------------------------------------------
      pusha
      MOV DH,DL
      MOV CL,4
      SHR DL,CL;右移4位获得高4位
      ADD DL,030H;0～9加30H,A~F加37H
      CMP DL,'9';将双分支转化为单分支
      JBE NEXT1
      ADD DL,7
NEXT1:MOV byte ptr[di],DL
      INC DI
      MOV DL,DH
      AND DL,0FH;高4位清0获得低4位
      ADD DL,30H
      CMP DL,'9'
      JBE NEXT2
      ADD DL,7
NEXT2:MOV byte ptr[di],DL
      popa
      ret
RHEX2ASCII endp
;=============================================================

;=============================================================
;子程序:将指定内存的ASCII数字修正成输出格式
;子程序调用名:FORMATNumString
;入口参数:CX=输入数字字符串长度 dl=对齐方式 0f0H=左对齐 0fh=右对齐 [SI]=数字字符串源地址,[di]=数字字符串目的地址
;出口参数:[di]中的字符串修正成为 需要的输出格式 CX=修正后的有效数字串长度
FORMATNumString proc near
;-------------------------------------------------------------
                push ax
		push bx
		push dx
		push di
		push si
		push bp
		mov dh,"0"
		cmp dh,[si]
		jne FIXALL
		push si
		push di
		push cx
		mov al," "
		cld
		rep stosb
		pop cx
		pop di
		pop si
		push cx
		mov ax,si
		xchg si,di
		push ax
		mov al,"0"
		cld
		repz scasb
		pop ax
		pop cx
		push di
		sub di,ax
		mov ax,di
		pop di
		cmp dl,0f0h
		je left
		add si,ax
		dec si
 left:
 		sub cx,ax
		xchg si,di
		dec si
		inc cx
		push cx
		cld
		rep movsb
		jmp FIXOK
FIXALL:
		push cx
		cld
		rep movsb
		FIXOK:pop cx
		pop bp
		pop si
		pop di
		pop dx
		pop bx
		pop ax
		ret
FORMATNumString endp
;=============================================================
sInt2ASCII_String proc near uses cx dx si di,pVar,buf,buf0
	local negative_flag:WORD
	mov negative_flag,FALSE
	.if dx == 0
		test ax,01000000000000000b
		jz be_positive16
		neg ax
		not negative_flag
		be_positive16:
		mov si,buf0
		mov di,buf
		mov WORD ptr [si],ax
		call HEX2BCD16
		xchg si,di
		mov cx,3
		@@:
		call HEX2ASCII
		inc si
		add di,2
		loop @b
		mov cx,6
		mov dl,0fh
		mov si,buf0
		mov di,pVar
		call FORMATNumString
		.if negative_flag == TRUE
			not negative_flag
			mov ax,6
			sub ax,cx
			dec ax
			add di,ax
			mov BYTE ptr es:[di],'-'
		.endif
	.else
		test dx,01000000000000000b
		jz be_positive32
		not dx
		not ax
		inc ax
		adc dx,0
		not negative_flag
		be_positive32:
		mov si,buf0
		mov di,buf
		mov WORD ptr [si],ax
		mov WORD ptr [si+2],dx
		call HEX2BCD32
		xchg si,di
		mov cx,5
		@@:
		call HEX2ASCII
		inc si
		add di,2
		loop @b
		mov cx,10
		mov dl,0fh
		mov si,buf0
		mov di,pVar
		call FORMATNumString
		.if negative_flag == TRUE
			not negative_flag
			mov ax,10
			sub ax,cx
			dec ax
			add di,ax
			mov BYTE ptr es:[di],'-'
		.endif		
	.endif
	ret
sInt2ASCII_String endp

;子程序名称：divdw
;功能：进行不会产生溢出的除法运算，被除数为dword型
;	   除数为word型，结果为dword型
;参数：	(ax)=dword型数据的低16位
;		(dx)=dword型数据的高16位
;		(cx)=除数
;返回：	(dx)=结果的高16位，(ax)=结果的低16位
;		(cx)=余数
;计算公式：X/N=int(H/N)*2^16+[rem(H/N)*2^16+L]/N
divdw proc
	jcxz divdw_return	;除数cx为0，直接返回
	push bx			;作为一个临时存储器使用，先保存bx的值
		
	push ax			;保存低位
	mov ax, dx		;把高位放在低位中
	mov dx, 0		;把高位置0
	div cx			;执行H/N，高位相除的余数保存在dx中
	mov bx, ax		;把商保存在bx寄存器中
	pop ax			;执行rem(H/N)*2^16+L
	div cx			;执行[rem(H/N)*2^16+L]/N，商保存在ax中
	mov cx, dx		;用cx寄存器保存余数
	mov dx, bx		;把bx的值复制到dx，即执行int(H/N)*2^16
						;由于[rem(H/N)*2^16+L]/N已保存于ax中，
						;即同时完成+运算
	pop bx			;恢复bx的值
	divdw_return:
	ret
divdw endp

clear_buf proc near uses ax cx di,pBuf,scCount
	mov cx,scCount
	mov di,pBuf
	mov al,' '
	rep stosb
	ret
clear_buf endp